package Explorer.Exp2;

import java.util.StringTokenizer;

import Agent.Percepts;
import Agent.Util;

import eis.exceptions.ActException;
import eis.iilang.Action;
import jade.core.AID;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;

public class ExplorerBehaviour extends Behaviour {

	private boolean move;
	
	public ExplorerBehaviour()
	{
		move =false;
	}
	
	@Override
	public void action() {
		
		AgentExplorer agent = (AgentExplorer)getAgent();
		if(!agent.isConnected())
			return;
		checkPercept();
		checkMessage();
		try {
			Action act = recharge();
			if(act != null)
			{
				agent.performAction(act);
				return;
			}
			act = probe();
			if(act != null)
			{
				agent.performAction(act);
				return;
			}
			act = exploration();
			if(act != null)
			{
				agent.performAction(act);
				return;
			}
			agent.performAction(Util.skipAction());
			return;
		}catch (ActException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public boolean done() {
		// TODO Auto-generated method stub
		return false;
	}

	public void checkPercept()
	{
		String position = null;
		
		AgentExplorer agent = (AgentExplorer)getAgent();
		
		boolean isProbe = false;
		boolean succes = false;
		
		for ( Percepts p : agent.getAllPercept() ) 
		{	
			if ( p.getName().equals("position") ) 
			{
				
				position = p.getValues().get(0);
				agent.removeBelief("position");
				
				agent.addBelief("position",position);
				
				for(String g : agent.getGoals())
				{
					if(g.equals("EdgeAVis-"+position))
					{
						agent.addGoal("Probe");
						break;
					}
				}
				agent.removeGoal("EdgeAVis-"+position);
				agent.addBelief("position",position);
			}
			else if ( p.getName().equals("visibleEdge") ) 
			{	
				for(String s : p.getValues())
				{
					StringTokenizer tk = new StringTokenizer(s);
					String vertex1 = tk.nextToken();
					String vertex2 = tk.nextToken();
					Noeud ver1, ver2;
					
					Graph graph = agent.getGraph();
					
					if(!graph.isPresent(vertex1))
					{
						agent.addGoal("EdgeAVis-"+vertex1);
						ver1 = new Noeud(vertex1);
						graph.addNoeud(ver1);
						
					}
					else
					{
						ver1 = graph.getNoeud(vertex1);
					}
					if(!graph.isPresent(vertex2))
					{
						agent.addGoal("EdgeAVis-"+vertex2);
						ver2 = new Noeud(vertex2);
						graph.addNoeud(ver2);
					}
					else
					{
						ver2 = graph.getNoeud(vertex2);
					}		
					
					boolean add = false;
					
					for(Arete a : ver1.getAretes())
					{
						if(a.getArrive() == ver2 )
							add = true;
					}
					
					if(add == false)
					{
						ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
						msg.setConversationId("Noeud");
						msg.setContent(vertex1+" "+vertex2+" 1");
						AID[] receiver =agent.getTeamAID(); 
						for(int i = 0; i<receiver.length;i++)
							msg.addReceiver(receiver[i]);
						ver1.addNoeud(ver2, 1);
						agent.send(msg);
					}
				}
				
			}
			else if(p.getName().equals("lastActionResult"))
			{
				if(p.getValues().get(0).equals("successful"))
					succes = true;
					
			}
			else if(p.getName().equals("lastAction"))
			{
				if(p.getValues().get(0).equals("probe"))
					isProbe = true;
			}
			
		}
		if(isProbe && succes)
		{
			ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
			msg.setConversationId("Prob");
			AID[] r = agent.getTeamAID();
			for(int i =0;i < r.length;i++)
				msg.addReceiver(r[i]);
			msg.setContent(position);
			agent.removeGoal("Probe");
			if(agent.isVerbose())
				System.out.println("Probe Action réussie");
		}
	}
	
	public Action exploration()
	{
	
		AgentExplorer agent = (AgentExplorer)getAgent();
		String pos = agent.getPercepts("position").getValues().get(0);
		Chemin road = agent.getChemin();
		Graph graph = agent.getGraph();
		
		if(agent.beliefExists("world-ok"))
		{
			if(agent.isVerbose())
				System.out.println("--> Monde Explore <--");
			return null;
		}
		if(move && pos.equals(road.getDernierNoeud()))
		{
			if(agent.isVerbose())
				System.out.println("Je suis arrive a destination - "+road.getDernierNoeud());
			move = false;
			road = new Chemin();
			return Util.probeAction();
			
		}
		else if(move)
		{
			boolean find = false;
			
			String noeud = null;
			if(agent.isVerbose())
				System.out.println("Depart -> !! ."+road.getDepart()+". pos ."+pos+".");
			if(pos.equals(road.getDepart()))
			{
				noeud = road.getListNoeud().get(0);
				find = true;
			}
			else
			{
				if(agent.isVerbose())
					System.out.println("Cherche ....");
				for(int i = road.getListNoeud().size()-1;i>=0 && !find;i--)
				{
					System.out.print("-> "+road.getListNoeud().get(i));
					if(agent.isVerbose())
						System.out.println("Determiner le noeud a atteindre");
					noeud = road.getListNoeud().get(i);
					
					if(!noeud.equals(pos))
						continue;
					
					find = true;
					noeud= road.getListNoeud().get(i+1);
					
				
				}
			}
			if(find)
			{
				if(agent.isVerbose())
					System.out.println("Je vais au noeud "+noeud);
				return Util.gotoAction(noeud);
			}
			if(agent.isVerbose())
			{
				System.out.println("Aucun noeud du chemin visible");
				System.out.println("Position -> "+pos);
				String ch = "";
				for(String s : road.getListNoeud())
					ch+=s+" -> ";
				System.out.println(ch);
				move =false;
			}
			return null;
			
		}
		else
		{
			if(agent.isVerbose())
				System.out.println("Cherche Noeud");
			move = true;
			int i = 3;
			for(String s : agent.getGoals())
			{
				if(agent.isVerbose())
					System.out.println("Goals : "+s);
				
				if(s.contains("EdgeAVis-"))
				{
					
					String v = s.substring(9);
					if(v.equals(pos))
						continue;
					road = graph.pathTo(pos,v);
					String r =""; 
					if(road != null && agent.isVerbose())
					{
						r+=road.getDepart();
						for(String n : road.getListNoeud())
							r+=n+" -> ";
						System.out.println("Route : "+r);
					}
				}	
				 if(road != null)
				{
					if(agent.isVerbose())
						System.out.println("Nouveau noeud a atteindre "+ road.getDernierNoeud());
					agent.setChemin(road);
					return exploration();
				}
			}
			if(agent.isVerbose())
				System.out.println("Probleme aucun noeud a atteindre");
			road = new Chemin();
		}
		
		return null;
	}
	
	public Action recharge()
	{
		AgentExplorer agent = (AgentExplorer)getAgent();
		
		if ( agent.getPercepts("energy") == null ) {
				System.out.println("Probleme je connais pas mon energy");
				return Util.skipAction();
		}
		
		double min = 0.1;
		int energy = Integer.parseInt(agent.getPercepts("energy").getValues().get(0));
		int max = Integer.parseInt(agent.getPercepts("maxEnergy").getValues().get(0)) ;
		if( energy < min * max) 
		{
			if(agent.isVerbose())
				System.out.println("Recharge -> energy : "+energy);
			return Util.rechargeAction();
		}

		if(agent.getPercepts("lastActionResult").getValues().get(0).equals("failed_resources"))
		{
			if(agent.getPercepts("lastAction").getValues().get(0).equals("probe"))
				agent.addGoal("Probe");
			return Util.rechargeAction();
		}
		
		return null;
	}

	public Action probe()
	{
		AgentExplorer agent = (AgentExplorer)getAgent();
		
		if(agent.goalExists("Probe"))
			return Util.probeAction();
			
		return null;
			
	}
	
	public void checkMessage()
	{
		
		AgentExplorer agent = (AgentExplorer)getAgent();
		ACLMessage msg = agent.receive();
		Graph graph = agent.getGraph();
		
		while(msg != null)
		{
			String id =msg.getConversationId(); 
			if(id.equals("Noeud"))
			{
				StringTokenizer tk = new StringTokenizer(msg.getContent());
				
				String s1= tk.nextToken();
				String s2 = tk.nextToken();
				String poids = tk.nextToken();
				
				Noeud n1 = null;
				Noeud n2 = null;
				
				if(!graph.isPresent(s1))
				{
					n1 = new Noeud(s1);
					graph.addNoeud(n1);
				}
				else
					n1 = graph.getNoeud(s1);
				
				boolean find = false;
				
				for(Arete a: n1.getAretes())
					if(a.getArrive().getName().equals(s2))
					{
						find = true;
						break;
					}
				
				if(!find)
				{
					if(agent.isVerbose())
						System.out.println("  Add Noeud --> "+msg.getContent());
					if(!graph.isPresent(s2))
					{
						n2 = new Noeud(s2);
						n1.addNoeud(n2,Integer.parseInt(poids));
						graph.addNoeud(n2);
					}
					else
						n1.addNoeud(graph.getNoeud(s2),Integer.parseInt(poids));
				}
						
			}
			else if(id.equals("Prob"))
			{
				agent.removeGoal("EdgeAVis-"+msg.getContent());
			}
			msg =agent.receive();
		}
	}
}
